<?php
/**
 * CONTENIDO extension pack (mpContenidoX), consists of multiple classes to
 * provide more features for Plugins/Modules.
 *
 * @package     mpContenidoX
 * @subpackage  Category
 * @author      Murat Purc <murat@purc.de>
 * @copyright   Copyright (c) 2008-2012 Murat Purc (http://www.purc.de)
 * @license     http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2
 * @version     $Id: Structure.class.php 21 2012-07-16 21:33:14Z purcaholic $
 */


defined('CON_FRAMEWORK') or die('Illegal call');


/**
 * Category structure class, to retieve categories/structure
 *
 * @package     mpContenidoX
 * @subpackage  Category
 * @author      Murat Purc <murat@purc.de>
 */
class mpCategory_Structure
{
    /**
     * List of self instances
     * @var  array
     */
    private static $_instances = array();

    /**
     * Category table name (con_cat)
     * @var  string
     */
    protected $_tableCat;

    /**
     * Category tree table name (con_cat_tree)
     * @var  string
     */
    protected $_tableCatTree;

    /**
     * Category language table name (con_cat_lang)
     * @var  string
     */
    protected $_tableCatLang;

    /**
     * Category article table name (con_cat_art)
     * @var  string
     */
    protected $_tableCatArt;

    /**
     * Article language table name (con_art_lang)
     * @var  string
     */
    protected $_tableArtLang;

    /**
     * Database instance
     * @var  DB_Contenido
     */
    protected $_db;

    /**
     * Structure array
     * @var  array
     */
    protected $_structure = array();

    /**
     * Client id
     * @var  int
     */
    protected $_client;

    /**
     * Language id
     * @var  int
     */
    protected $_lang;

    /**
     * List of debug messages
     * @var  array
     */
    protected $_debugMsgs = array();


    public function __construct($client, $lang)
    {
        $this->_client = (int) $client;
        $this->_lang   = (int) $lang;
        $this->_db     = new DB_Contenido();

        $this->_tableCat     = $GLOBALS['cfg']['tab']['cat'];
        $this->_tableCatTree = $GLOBALS['cfg']['tab']['cat_tree'];
        $this->_tableCatLang = $GLOBALS['cfg']['tab']['cat_lang'];
        $this->_tableCatArt  = $GLOBALS['cfg']['tab']['cat_art'];
        $this->_tableArtLang = $GLOBALS['cfg']['tab']['art_lang'];
    }


    private function __clone()
    {
    }


    /**
     * Returns self instance, created by passed client and language
     *
     * @param   int  $client
     * @param   int  $lang
     * @return  mpCategory_Structure
     */
    public static function getInstance($client, $lang)
    {
        $key = (string) $client . '-' . (string) $lang;
        if (!isset(self::$_instances[$key])) {
            self::$_instances[$key] = new self($client, $lang);
        }
        return self::$_instances[$key];
    }


    public function getStructure()
    {
        if (count($this->_structure) == 0) {
            $this->reloadStructure();
        }
        return $this->_structure;
    }


    /**
     * Loads the category tree structure.
     *
     * @return  void
     */
    public function reloadStructure()
    {
        $this->_structure = array();

        $db = new DB_Contenido();
        $sql = "SELECT
                    c.preid, c.postid, c.parentid, ct.idcat, ct.level, cl.name, cl.public,
                    cl.visible, cl.idlang
                FROM
                    {$this->_tableCat} AS c,
                    {$this->_tableCatLang} AS cl,
                    {$this->_tableCatTree} AS ct
                WHERE
                    c.idclient = {$this->_client} AND
                    cl.idlang  = {$this->_lang} AND
                    ct.idcat   = cl.idcat AND
                    cl.idcat   = c.idcat
                ORDER BY
                    ct.idtree ASC";
        $this->_debugMsgs[] = 'loadStructure() 1. sql:' . $sql;
        $db->query($sql);
        $aIn = array();
        while ($db->next_record()) {
            $aIn[] = (int) $db->f('idcat');
        }
        $sIn = implode(',', $aIn);

        $sql2 = "SELECT
                     ca.idcat, al.idart, idlang
                 FROM
                    {$this->_tableArtLang} AS al,
                    {$this->_tableCatArt} AS ca
                 WHERE
                     ca.idcat IN (". $sIn.") AND
                     al.idlang = {$this->_lang} AND
                     ca.idart = al.idart";
        $this->_debugMsgs[] = 'loadStructure() 2. sql:' . $sql2;
        $this->_db->query($sql2);
        $articlesCache = array();
        while ($this->_db->next_record()) {
            $articlesCache[$this->_db->f('idcat')][$this->_db->f('idart')][$this->_db->f('idlang')] = 'x';
        }

        $db->seek(0);
        while ($db->next_record()) {
            $entry = array();
            $entry['articles'] = false;
            $arts = array();
            if (isset($articlesCache[$db->f('idcat')])) {
                foreach ($articlesCache[$db->f('idcat')] as $key => $value) {
                    foreach ($value as $key2 => $value2) {
                        $arts[$key][$key2] = 1;
                    }
                }
            }
            foreach ($arts as $idart => $entry) {
                if (is_array($entry)) {
                    if (!array_key_exists($this->_lang, $entry)) {
                        //$entry['articles'] = true;
                        $aIsArticles[$db->f('idcat')] = true;
                        break;
                    }
                }
            }
        }

        $sql = "SELECT DISTINCT
                    c.idcat, c.parentid, c.preid, c.postid, cl.name, cl.idlang, cl.visible, cl.public, ct.level
                FROM
                    {$this->_tableCat} AS c
                LEFT JOIN
                    {$this->_tableCatLang} AS cl ON c.idcat = cl.idcat
                LEFT JOIN
                    {$this->_tableCatTree} AS ct ON (c.idcat = ct.idcat AND cl.idcat = ct.idcat)
                WHERE
                    c.idclient = {$this->_client} AND
                    cl.idlang = {$this->_lang}
                ORDER BY ct.idtree ASC";
        $this->_debugMsgs[] = 'loadStructure() 3. sql:' . $sql;
        $this->_db->query($sql);
        while ($this->_db->next_record()) {
            if (!isset ($this->_structure[$this->_db->f('parentid')][$this->_db->f('idcat')])) {
                $rs = array();
                $rs['idcat']    = $this->_db->f('idcat');
                $rs['parentid'] = $this->_db->f('parentid');
                $rs['preid']    = $this->_db->f('preid');
                $rs['postid']   = $this->_db->f('postid');
                $rs['name']     = $this->_db->f('name');
                $rs['idlang']   = $this->_db->f('idlang');
                $rs['visible']  = $this->_db->f('visible');
                $rs['public']   = $this->_db->f('public');
                $rs['level']    = $this->_db->f('level');
                $rs['articles'] = $aIsArticles[$rs['idcat']];

                $this->_structure[$rs['parentid']][$rs['idcat']] = $rs;
            }
        }
    }


    public function getCategory($catId)
    {
        foreach ($this->_structure as $parentId => $cats) {
            if (isset($cats[$catId])) {
                return $cats[$catId];
            }
        }
    }


    /**
     * Returns list of subcategories (recursive). Pass 0 (zero) to get all available category ids.
     *
     * @param   int    $catId
     * @return  array  List of category ids
     */
    public function getSubCategoryIds($catId)
    {
        $catId = (int) $catId;
        $catIdList = array();
        if (isset($this->_structure[$catId])) {
            foreach ($this->_structure[$catId] as $subCatId => $item) {
                $catIdList[] = $subCatId;
                $catIdList = array_merge($catIdList, $this->getSubCategoryIds($subCatId));
            }
        }
        return $catIdList;
    }


    public function getStrTree($catId)
    {
        return $this->_getStrTree($catId);
    }


    protected function _getStrTree($catId)
    {
        $catId      = (int) $catId;
        $activepath = array();
        $subCats    = array();

        if (isset($this->_structure[$catId])) {
            foreach ($this->_structure[$catId] as $key => $item) {
                $currCatId = (int) $item['idcat'];

                $subTree = $this->_getStrTree($currCatId);
                if ($subTree['activepath']) {
                    $item['active'] = 'activepath';
                }
                $item['sub'] = $subTree;

                $subCats[] = $item;

                if ($item['active'] != '') {
                    $activepath = $item;
                }
            }
        }

        $return = array('item' => $subCats, 'activepath' => $activepath);
        return $return;
    }


    public function getDebugMsgs()
    {
        return $this->_debugMsgs;
    }
}